#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

// lambda表达式 ---- 匿名函数
//struct Goods
//{
//	string _name;
//	double _price;
//	int _evaluate;
//	//.....
//
//	Goods(const char* str, double price, int evaluate)
//		:_name(str)
//		, _price(price)
//		, _evaluate(evaluate)
//	{}
//
//};
//
//struct ComparePriceLess
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return gl._price < gr._price;
//	}
//};
//
//struct ComparePriceGreater
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return  gl._price > gr._price;
//	}
//};
//
//int main()
//{
//	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 },
//						{ "橙子", 2.2,3 }, { "菠萝", 1.5, 4 } };
//
//	sort(v.begin(), v.end(), ComparePriceLess());
//	sort(v.begin(), v.end(), ComparePriceGreater());
//
//	//价格升序
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
//		{
//			return g1._price < g2._price;
//		});
//
//	//返回值类型：bool
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)-> bool
//		{
//			return g1._price < g2._price;
//		});
//
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
//		{
//			return g1._evaluate < g2._evaluate;
//		});
//
//	return 0;
//}

//int main()
//{
//	auto add1 = [](int x, int y)->int {return x + y; };
//	cout << add1(1, 2) << endl;
//
//	auto func1 = []()->int
//		{
//			cout << "hello xlf" << endl;
//			cout << "hello world" << endl;
//			return 0;
//		};
//
//	func1();
//
//	//返回值类型可自动推到，所以可以省略
//	//无参数可以省略
//	auto func2 = []
//		{
//			cout << "hello xlf" << endl;
//			cout << "hello world" << endl;
//			return 0;//有返回值可以省略返回类型
//		};
//
//	cout << func2() << endl;
//
//	return 0;
//}


//int main()
//{
//	// 最简单的lambda表达式, 该lambda表达式没有任何意义
//	[] {};
//
//	// 省略参数列表和返回值类型，返回值类型由编译器推导为int
//	int a = 3, b = 4;
//	[=] {return a + 3; };
//
//	// 省略了返回值类型，无返回值类型
//	auto fun1 = [&](int c) {b = a + c; };
//	fun1(10);
//		cout << a << " " << b << endl;
//
//	// 各部分都很完善的lambda函数
//	auto fun2 = [=, &b](int c)->int {return b += a + c; };
//	cout << fun2(10) << endl;
//
//	// 复制捕捉x
//	int x = 10;
//	auto add_x = [x](int a) mutable { x *= 2; return a + x; };
//	cout << add_x(10) << endl;
//	return 0;
//} 


//void (*PF)();
//int main()
//{
//    auto f1 = [] {cout << "hello world" << endl; };
//    auto f2 = [] {cout << "hello world" << endl; };
//   
//    // 允许使用一个lambda表达式拷贝构造一个新的副本
//    auto f3(f2);
//    f3();
//    // 可以将lambda表达式赋值给相同类型的函数指针
//    PF = f2;
//    PF();
//    return 0;
//}

//int main()
//{
//	int a = 0, b = 1;
//	auto swap1 = [](int& x, int& y)
//		{
//			//只能用当前lambda局部域和捕捉的对象
//			int temp = x;
//			x = y;
//			y = temp;
//		};
//
//	swap1(a, b);
//
//	// 捕捉列表
//	// 传值捕捉本质是一种拷贝，并且const修饰了
//	// mutable相当于去掉const属性，可以修改了
//	// 但是修改了不会影响外面被捕捉的值，因为只是外面变量的一种拷贝
//	auto swap2 = [a, b]() mutable//传值（const）捕捉的值是不能改变的
//		{
//			int temp = a;
//			a = b;
//			b = temp;
//		};
//
//	swap2();
//
//	auto swap2 = [&a, &b]() //引用捕捉（不是const，是别名）
//		{
//			int temp = a;
//			a = b;
//			b = temp;
//		};
//
//	return 0;
//}

//int x = 0;//全局
//int main()
//{
//	//只能用当前lambda局部域和捕捉的对象和全局对象
//
//	int a = 0, b = 1, c = 2, d = 3;
//	//所有值传值捕捉
//	auto func1 = [=]
//		{
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	//所有值引用捕捉
//	auto func1 = [&]
//		{
//			a++;
//			b++;
//			c++;
//			d++;
//			int ret = a + b + c + d + x;//全局的x也可以用
//			return ret;
//		};
//
//	//混合捕捉1
//	auto func1 = [&a, b]// a 传引用捕捉， b 传值（const）捕捉（b 不能修改，加mutable可修改）
//		{
//			a++;
//			//b++;
//			int ret = a + b;
//			return ret;
//		};
//
//
//	//混合捕捉2
//	//所有值以引用方式捕捉，d用传值捕捉
//	auto func1 = [&, d]
//		{
//			a++;
//			b++;
//			c++;
//			//d++;
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	// 注意：
//	// mutable虽然可以去掉const属性，可以修改函数体里面的变量，但是一般不用
//	// 因为怕误用，怕有一些人认为修改了lambda函数体里面的变量，就可以影响外面的
//	// 其实是不影响外面的。
//
//
//
//	//混合捕捉3
//	//所有值以传值方式捕捉，d用引用捕捉
//	auto func1 = [=, &d]//如果用来lambda就表示在函数体里面 a b c 都先++了，
//		{                 //ret的值是a b c ++之后的值，但是里面abc对外面是没有影响的
//			//a++;        // &d 才对外面的 d 有影响
//			//b++;        // 所以 mutable 要慎用
//			//c++;
//			d++;
//			int ret = a + b + c + d;
//			return ret;
//		};
//
//	return 0;
//}


// lambda 匿名函数对象
// 捕捉列表的对象是成员变量存在lambda类对象中
// 捕捉的本质是构造函数的初始化参数

//class Rate
//{
//public:
//	Rate(double rate) : _rate(rate)
//	{}
//
//	double operator()(double money, int year)
//	{
//		return money * _rate * year;
//	}
//
//private:
//	double _rate;
//};
//
//int main()
//{
//	// 函数对象
//	double rate = 0.015;
//	Rate r1(rate);
//	r1(10000, 2);
//
//	// lamber
//	auto r2 = [=](double monty, int year)->double
//		{
//			return monty * rate * year;
//		};
//
//
//	auto r3 = [=](double monty, int year)->double
//		{
//			return monty * rate * year;
//		};
//
//	r2(10000, 2);
//
//	return 0;
//}

// 包装器
ret = func(x);
// 上面func可能是什么呢？那么func可能是函数名？函数指针？函数对象(仿函数对象)？也有可能
// 是lamber表达式对象？所以这些都是可调用的类型！如此丰富的类型，可能会导致模板的效率低下！
// 为什么呢？我们继续往下看
template<class F, class T>
T useF(F f, T x)
{
    static int count = 0;
    cout << "count:" << ++count << endl;
    cout << "count:" << &count << endl;
    return f(x);
}

double f(double i)
{
    return i / 2;
}

struct Functor
{
    double operator()(double d)
    {
        return d / 3;
    }
     
};

int main()
{
    // 函数名
    cout << useF(f, 11.11) << endl;
    // 函数对象
    cout << useF(Functor(), 11.11) << endl;
    // lamber表达式
    cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;

    return 0;
}


